# Web Worker使用

Web Worker可以用来创造多线程环境,允许主线程把一些计算密集型或高延迟的任务分配给Worker线程,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢,两者互不干扰。使用Worker单独开一个js来处理一些占内存耗性能的任务。

Web Worker 有以下几个使用注意点:

  • 同源限制:分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。

  • DOM 限制:Worker线程中无法获取DOM对象,但可以使用navigator和location。

  • 通信联系:Worker线程和主线程不能直接通信,必须通过消息完成。

  • 脚本限制:Worker 线程不能执行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。

  • 文件限制:Worker 线程无法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络。

# 1、创建Worker线程

在主线中我们程使用Worker构造函数加载一个单独的JS文件,新建一个线程。加载的这个JS文件就是Worker线程所要执行的任务。

var worker = new Worker('/work.js');

Worker线程JS文件

// work.js
console.log('worker线程');

# 2、相互通信

主线程和Worker线程之间发送和接收都是通过postMessage方法和监听message事件进行。

Worker 之间的通信内容,可以是文本、对象,也可以是二进制数据,比如 File、Blob、ArrayBuffer 等类型。正常数据通信数据不会相互影响,如果是二进制数据的话,为了节省性能,JS会进行特殊处理,一但传输给子线程后,主线程就无法再使用这些数据。

主线程发送和接收:

var worker = new Worker('/work.js');

// 主线程发送消息
worker.postMessage('Hello World');
worker.postMessage({
  name: 'xxx',
  age: 18
});

// 主线程接收消息
worker.onmessage = function (event) {
  // event.data 就是接受的数据
  console.log(event.data);
};

// 监听错误
worker.onerror = function (event) {
  console.log(event);
};

Worker线程发送和接收:

// self是子线程的全局对象

// 子线程发送消息
self.postMessage('Hello World');
self.postMessage({
  name: '111',
  age: 111
});

// 子线程接收消息
self.onmessage = function (event) {
  // event.data 就是接受的数据
  console.log(event.data);
};

// 监听错误
self.onerror = function (event) {
  console.log(event);
};

# 3、Worker中加载脚本

Worker 内部如果要加载其他脚本,有一个专门的方法importScripts()。

// 加载脚本
self.importScripts("/spark-md5.min.js");
// 加载多个脚本
self.importScripts('script1.js', 'script2.js');

# 4、关闭Worker

使用完成后,为了节省系统资源,必须关闭 Worker。

// 主线程
worker.terminate();

// Worker线程
self.close();